import {_decorator, Component, director} from "cc";
import {WorldEvent} from "db://assets/script/common/events/world-event";
import {GameEvent} from "db://assets/script/game-event";

const {ccclass, property} = _decorator;

@ccclass('WorldPubSubServer')
export class WorldPubSubServer extends Component {
    private _store: Map<string, WorldEvent[]> = new Map<string, WorldEvent[]>();
    private _ackFlag: Map<string, boolean> = new Map<string, boolean>();

    start() {
        director.on(GameEvent.worldPubSubAck, this.ack, this);
    }

    ack(topic: string) {
        if (!this._store.has(topic)) {
            console.log('topic ack: ', topic)
            this._ackFlag.set(topic, true);
            director.emit(GameEvent.worldPubSubAckCompletePrefix + topic, 1);
        }
    }

    publish(topic: string, event: WorldEvent) {
        if (this._store.has(topic)) {
            console.log('topic publish: ', topic);
            this._store.get(topic).push(event);
            director.emit(GameEvent.worldPubSubMessageArrivedPrefix + topic, 1);
        } else {
            console.warn('Unknown topic: ' + topic);
        }
    }

    pullSingle(topic: string): WorldEvent {
        console.log('try topic pull: ', topic);
        if (this._store.has(topic) && this._ackFlag.get(topic)) {
            console.log('topic pull: ', topic);
            this._ackFlag.set(topic, false);
            return this._store.get(topic).shift()
        }
        return null
    }

    pull(topic: string, batchSize: number): WorldEvent[] {
        if (this._store.has(topic) && this._ackFlag.get(topic)) {
            this._ackFlag.set(topic, false);
            const rst = this._store.get(topic).slice(0, batchSize);
            this._store.set(topic, this._store.get(topic).slice(batchSize));
            return rst
        }
        return []
    }

    subscribe(topic: string) {
        if (!this._store.has(topic)) {
            this._store.set(topic, []);
            this._ackFlag.set(topic, true);
        }
    }


}